package com.taysear.parcel;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;

import com.taysear.parcel.domain.Permission;
import com.taysear.parcel.domain.Role;
import com.taysear.parcel.domain.RolePermission;
import com.taysear.parcel.domain.User;
import com.taysear.parcel.domain.UserRole;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.event.dd.acceptcriteria.SourceIs;
import com.vaadin.ui.Button;
import com.vaadin.ui.Form;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.themes.Reindeer;

public class AssignPermissionsWindow extends Window{
	ParcelApplication app;
	int selectedUserId;
	PermissionTable availablePermissionsTable;
	PermissionTable selectedUserPermissionsTable;
	List<Permission> selectedUserPermissionsList = new ArrayList<Permission>();

	public AssignPermissionsWindow(ParcelApplication app, int selectedUserId) {
		super("Assign permissions");
		this.app = app;
		this.selectedUserId = selectedUserId;
		
		Form form = new Form();
		form.setCaption(" ");
		form.setSizeFull();
		
		BeanItemContainer<Permission> availablePermissionsContainer = new BeanItemContainer<Permission>(Permission.class);
		BeanItemContainer<Permission> selectedUserCurrentPermissionsContainer = new BeanItemContainer<Permission>(Permission.class);
		List<Permission> availablePermissionsList = new ArrayList<Permission>();
		
		Role currentUserRole = (Role) app.em.createQuery("SELECT ur.role FROM UserRole ur Where ur.user.userId = " + app.getUser().getUserId()).getSingleResult();
		try {
			Role selectedUserRole = (Role) app.em.createQuery("SELECT ur.role FROM UserRole ur Where ur.user.userId = " + selectedUserId).getSingleResult();
			selectedUserPermissionsList = app.em.createQuery("SELECT rp.permission FROM RolePermission rp Where rp.role.id = " + selectedUserRole.getId() +" order by rp.permission.groupId, rp.permission.id").getResultList();
		} catch (NoResultException e) {
		}
		
		if("admin".equalsIgnoreCase(app.getUser().getUsername())){
			availablePermissionsList = app.em.createQuery("SELECT p FROM Permission p Where p.id != 1 order by p.groupId, p.id").getResultList();
		}
		else {
			availablePermissionsList = app.em.createQuery("SELECT rp.permission FROM RolePermission rp Where rp.role.id = " + currentUserRole.getId() +" order by rp.permission.groupId, rp.permission.id").getResultList();
		}
		
		selectedUserCurrentPermissionsContainer.addAll(selectedUserPermissionsList);
		for (Permission ap : availablePermissionsList) {
			if(!selectedUserPermissionsList.contains(ap))
				availablePermissionsContainer.addBean(ap);
		}
		
		String[] visibleColumns = new String[] {"Permission"};
		availablePermissionsTable = new PermissionTable("Available permissions", availablePermissionsContainer, visibleColumns);
		selectedUserPermissionsTable = new PermissionTable("Selected user permissions", selectedUserCurrentPermissionsContainer, visibleColumns);
		availablePermissionsTable.initializeTable(new SourceIs(selectedUserPermissionsTable), availablePermissionsContainer);
		selectedUserPermissionsTable.initializeTable(new SourceIs(availablePermissionsTable), selectedUserCurrentPermissionsContainer);
					 
		FormLayout formLayout = (FormLayout) form.getLayout();
		HorizontalLayout horizontalLayout = new HorizontalLayout();
		horizontalLayout.setSpacing(true);
		horizontalLayout.addComponent(availablePermissionsTable);
		horizontalLayout.addComponent(selectedUserPermissionsTable);
		formLayout.addComponent(horizontalLayout);
		
		Button save = new Button("Save", new Button.ClickListener() {
			@Override
			public void buttonClick(ClickEvent event) {
			savePermissions();	
			}
		});
		save.setStyleName(Reindeer.BUTTON_SMALL);
		Button close = new Button("Close", new Button.ClickListener() {
			@Override
			public void buttonClick(ClickEvent event) {
				Window window = (Window) event.getButton().getParent().getParent().getParent().getParent();
				window.getParent().removeWindow(window);
			}
		});
		close.setStyleName(Reindeer.BUTTON_SMALL);
		form.getFooter().addComponent(save);
		form.getFooter().addComponent(close);
		
    	center();
    	setModal(true);
		VerticalLayout verticalLayout = (VerticalLayout) getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
    	verticalLayout.addComponent(form);
	}
	
	private void savePermissions() {
		EntityManager em = app.em;
		List<Permission> add = new ArrayList<Permission>();
		try{
			em.getTransaction().begin();
			BeanItemContainer<Permission> selectedPermissions = (BeanItemContainer<Permission>) selectedUserPermissionsTable.getContainerDataSource();
			Role selectedUserRole = (Role) app.em.createQuery("SELECT ur.role FROM UserRole ur Where ur.user.userId = " + selectedUserId).getSingleResult();
			List<RolePermission> selectedUserRolesPermissionsList = em.createQuery("SELECT rp FROM RolePermission rp Where rp.role.id = " + selectedUserRole.getId()).getResultList();
			List<Permission> remove = new ArrayList<Permission>();
			remove.addAll(selectedUserPermissionsList);
			for (Permission p : selectedPermissions.getItemIds()) {
				if(!selectedUserPermissionsList.contains(p))
					add.add(p);
				else
					remove.remove(p);
			}
			
			for (Permission permissions : add) {
				RolePermission rp = new RolePermission();
				rp.setRole(selectedUserRole);
				rp.setPermission(permissions);
				em.persist(rp);
			}
			for (RolePermission rp : selectedUserRolesPermissionsList) {
				if(remove.contains(rp.getPermission()))
					em.remove(rp);
			}
			
			em.getTransaction().commit();
			app.showNotification("Permissions successfully saved.");
		} catch (NoResultException e) {
			User user = em.find(User.class, selectedUserId);
			Role role = new Role();
			role.setRolename(user.getUsername());
			em.persist(role);
			
			UserRole userRoles = new UserRole();
			userRoles.setRole(role);
			userRoles.setUser(user);
			userRoles.setUsername(user.getUsername());
			em.persist(userRoles);
			
			for (Permission permissions : add) {
				RolePermission rp = new RolePermission();
				rp.setRole(role);
				rp.setPermission(permissions);
				em.persist(rp);
			}
			em.getTransaction().commit();
			app.showNotification("Permissions successfully saved.");
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
}
